{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "id": "7-tQfVM_pJcr"
   },
   "source": [
    "<div id=\"colab_button\">\n",
    "  <h1>Whisper integration</h1>\n",
    "  <a target=\"_blank\" href=\"https://colab.research.google.com/github/mithril-security/blindai/blob/main/docs/docs/tutorials/api/whisper_tutorial.ipynb\"> \n",
    "  <img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>\n",
    "</div>\n",
    "______________________________\n",
    "\n",
    "In this tutorial, we'll **transcribe an audio file** with **privacy guarantees** using the popular model **Whisper** with **BlindAI API**. Whisper is an open-source automatic speech recognition (ASR) system trained on 680,000 hours of multilingual and multitask supervised data collected from the web."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "id": "eyZHW8TvpJc1"
   },
   "source": [
    "## Installation\n",
    "________________________________________________________\n",
    "\n",
    "Before we begin, you will need to install the [blindai](https://pypi.org/project/blindai/) Python library and download an example [test audio file](https://www2.cs.uic.edu/~i101/SoundFiles/taunt.wav). This one was provided by University of Illinois at Chicago  as part of their Computer Science 101 course."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 1000
    },
    "id": "169vRU_vpJc4",
    "outputId": "84758615-d31c-42cf-a343-d492bbec326c"
   },
   "outputs": [],
   "source": [
    "# install blindai\n",
    "!pip install blindai\n",
    "\n",
    "# Download our example audio file and save it as `taunt.wav`\n",
    "!wget https://www2.cs.uic.edu/~i101/SoundFiles/taunt.wav -O taunt.wav"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "id": "ERGjq-kWpJc7"
   },
   "source": [
    "## Transcribing the audio file\n",
    "______________________________________________\n",
    "\n",
    "Speech-to-text operations are handled within the `Audio.transcribe` module of `BlindAI.api`.\n",
    "\n",
    "To transcribe an audio file, we call the `transcribe` method and provide the path to our audio file as the `file` option. The Whisper model accepts a variety of audio file formats (m4a, mp3, mp4, mpeg, mpga, wav, webm)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 273,
     "referenced_widgets": [
      "ee84f4d759f34951a91a5a1b455208ad",
      "2cd128aa0f3d46bc8170bfc4a7c84b42",
      "60ae2a98c06741029653cf9c30a821a5",
      "4ead236935e54af49afc0b4980069195",
      "e6653a9cc5274c75a5f7a6c92bc6f9da",
      "5157f8008edb4200b68389b05524a02c",
      "c39c98e0429f4f60869b4d5788392383",
      "1c7bf304a3b0459582b3b9b00081fdd6",
      "1fae9b7a44994a008cb8bb252e685687",
      "60495b7a331f47a4930096fe32e20c4a",
      "d4e1ea5ef241436faa57799a1ce9c16b",
      "2710f779e19946058617870bd0da4f95",
      "6d5d0205b7d9427383bc31aaed3ff1fa",
      "bbdb6ed65bb643c891a33cae67338c1e",
      "6d6d8545e65b438eb3ad04fdd3fcb523",
      "74404a89a6c14f89aca54b30728e230f",
      "033fd5b05f9e4a78a722ca26a345bb3c",
      "39b165663ddd421ca8752e8feba65865",
      "816a7897f85144e4b998b9e28cf466aa",
      "d09544c3d67d41fda6ebaa478ae9e5cc",
      "f39fd6afe02a4885896cc584f690f879",
      "6131a0a6c8a24fcb9230c3e472594140",
      "2f5c32f982bb4162a5e64e3dc6448738",
      "4493aec3b9eb45cd957558dc26787ed0",
      "1e9ebe05821c46b0b23413f51c8359b9",
      "88ec36be4d054191aaf82b550e6f073c",
      "eb74b7b0a973437085d343de925d7231",
      "d12b7be2981c43e19fa382719ff1c8d4",
      "dff9989f6cac49b595ae0cd214a01782",
      "d43ef1c2420c4404b55a3382509b5cda",
      "60902f59155040efaadf53b932db327a",
      "f3563900a4ad450c892f15abf6c6e699",
      "844e422fead140acbc0a6c9a43210c6b",
      "8fbd72b5d88a4541b4250917c4348ad1",
      "e3ee9c2925824a61ad77392c32a24bca",
      "b9e0d70632de4b0383ff482d1490f376",
      "7e5de6d7f09448c9a7ffbed90767728e",
      "946d166d8dc147c6a809776a6643a617",
      "ae40764fcfa148c6a3692f80d3cccd09",
      "44720415a71343fdb025f1dd1c2568e7",
      "78b3f6e59b944b799f640caf1ba881fb",
      "7e4f3efb85cc415d97c1ec68f30d1b22",
      "cfc656d292524fc2b1ed1886161e5efc",
      "f159743fb4eb481f97cc1f5a87da17c1",
      "131e7f70ffae445abb18f217656c19e1",
      "93412079cd064d1e87e60aee53c60e6e",
      "dd8044dc18664a759b6a9cb0f0fe0af0",
      "c14611b41d1c4d5da2c2716652c7ea81",
      "2dd6172804614fd6a36119bebbe35614",
      "6e0f131f29674861979c2a9c99bdf43e",
      "8e5cc6416c6444d386f28b1c13d297fb",
      "f9ad47b633874822886cc27363b2bcb1",
      "0bcf054117d344e29055d2094bbbd784",
      "40f3ab6379074a87b7ee823acc2e57f5",
      "2da8072665384f3fbffa53234b581178",
      "e663fcefc1824576898a9b2903be164f",
      "2153525666b84829b4797cdfb1b820b3",
      "dba0e84c053442348e272e0cbba2b3a7",
      "6e7948c385714b57bf693ac16e33fa26",
      "8c7575c221f24eb4bcb5e3f59faea6cb",
      "6daf9a3b95274b1889402321fe6cf43d",
      "8c67134ac5584ee5a921c0d7a421ddb3",
      "b63ea64575f64a838193ef1e57792fc0",
      "8703bef47e864fc08c8b7603ead3aa53",
      "462d82a18ff4497a92a2544bc09ee63d",
      "e3461dec5d1e472f982cbf331b50d83d",
      "9ac05cfc18f24be7b532c57d0e671f10",
      "2077fc95d4d846ff998cd508096eddb4",
      "54cd6b54db344d31986f5fa6eea60f63",
      "46071c3cafc949219e9fb526b7a8183a",
      "7354a1e8a5064df1908b385508b36d8b",
      "20775b71b9cf4204aad7c93b2fe51d41",
      "7cba9c4f745f486489fadb646844472a",
      "60bbcf95c0394fe185e54048dfaff257",
      "edda9299e7dc4111b3bfbfbf57faa7d0",
      "8a611e4466034ec3941b34a40dc63141",
      "cd2d631b6d36469c8fb323cbff0c9e75",
      "fcc64f5b355641d6ae666de9d3a1fdea",
      "a71daf69814a4e978d60559229b01b09",
      "378c850824b74707af12fe6a6cbe32a7",
      "48bdb108621141bf9ee7708e190227a4",
      "cd678dd8a42942d2a24365151d73fc97",
      "b650175af27947b092855da90abd9144",
      "4b46beeae1114f75a730e5b74b9bb599",
      "c207f8913def41d8af876a68168b5661",
      "55393379502f4325bca8928346b59c6b",
      "f4d78d75393446ed99af43e70cbf442a",
      "2db617c1936848dabe5dad3715afc345"
     ]
    },
    "id": "U156nalXpJc9",
    "outputId": "f9733f35-72e3-480d-e40e-30b6f52eba8a"
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "ee84f4d759f34951a91a5a1b455208ad",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)rocessor_config.json:   0%|          | 0.00/185k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "2710f779e19946058617870bd0da4f95",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)okenizer_config.json:   0%|          | 0.00/844 [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "2f5c32f982bb4162a5e64e3dc6448738",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)olve/main/vocab.json:   0%|          | 0.00/999k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "8fbd72b5d88a4541b4250917c4348ad1",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)/main/tokenizer.json:   0%|          | 0.00/2.13M [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "131e7f70ffae445abb18f217656c19e1",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)olve/main/merges.txt:   0%|          | 0.00/456k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "e663fcefc1824576898a9b2903be164f",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)main/normalizer.json:   0%|          | 0.00/52.7k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "9ac05cfc18f24be7b532c57d0e671f10",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)in/added_tokens.json:   0%|          | 0.00/2.08k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "fcc64f5b355641d6ae666de9d3a1fdea",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading (…)cial_tokens_map.json:   0%|          | 0.00/1.72k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import blindai\n",
    "\n",
    "transcript = blindai.api.Audio.transcribe(\"taunt.wav\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "id": "vuBi3JTYpJc_"
   },
   "source": [
    ">If you or your service provider are running your own instance of the BlindAI server and you don't wish to connect to our managed cloud solution, you can pass your `BlindAiConnection` client object to the `transcribe` method's `connection` option."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "id": "ueVmCHykpJdB"
   },
   "source": [
    "We can print out the returned `transcript` string variable to check our results are as expected."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "-RIltp58pJdB",
    "outputId": "5c435f8c-6863-4493-fcb3-237352bcd46c"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " Now go away, or I shall taunt you a second timer!\n"
     ]
    }
   ],
   "source": [
    "print(transcript)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "id": "fww_D5W22wlv"
   },
   "source": [
    "Our audio file has been correctly transcribed! \n",
    "\n",
    "Feel free to test this out with your own audio files 🔊"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "id": "1BjHoYN1PNr_"
   },
   "source": [
    "\n",
    "## Under the hood\n",
    "______________________________________________\n",
    "\n",
    "Let's take a moment to discuss what went on under the hood when we called the `blindai.api.Audio.transcribe()` method. This will allow you to understand better how data privacy is guaranteed by the hardware. \n",
    "\n",
    "### Connection\n",
    "\n",
    "First, the `transcribe()` method connects to our managed cloud solution by calling the BlindAI.Core's `connect()` method, with the following code:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "id": "B3soukHvQwoO"
   },
   "outputs": [],
   "source": [
    "DEFAULT_BLINDAI_ADDR = \"4.246.205.63\"\n",
    "\n",
    "connection = blindai.core.connect(\n",
    "    DEFAULT_BLINDAI_ADDR,\n",
    "    hazmat_http_on_unattested_port=True,\n",
    ")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "id": "f2blJaY5SD2R"
   },
   "source": [
    "It is at this point that the attestation process is triggered. There is a technical explanation of what goes on in [our confidential computing guide](https://blindai.mithrilsecurity.io/en/latest/docs/getting-started/confidential_computing/). \n",
    "\n",
    "But if you haven't read it yet, all you need to know at this point is that the attestation process **verifies** that the **application code** running in the enclave has **not been modified**. To do so, it will check that the Mithril server instance is running a real enclave using **genuine hardware**. \n",
    "\n",
    "The client will also check the application code running in the enclave exactly matches the expected code for the latest release of BlindAI. The code is defined in the client's built-in `manifest.toml` file. This step prevents users from being able to connect with a version of the application which has been tampered with and may not be trustworthy.\n",
    "\n",
    "We can quickly prove that this check is in place by doing the following:\n",
    "1. Creating an empty `manifest.toml` file called `fake_manifest.toml`\n",
    "2. Using the `connect()` method's `hazmat_manifest_path()` option to override the default path for the `manifest.toml` file with the path for our `fake_manifest.toml` file\n",
    "\n",
    "Uncomment and run the following code to see this for yourself."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 469
    },
    "id": "4xCEJSZmREwH",
    "outputId": "ca195d1e-b1bf-42fc-b9df-8c9863ba56b4"
   },
   "outputs": [
    {
     "ename": "AttestationError",
     "evalue": "ignored",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m/usr/local/lib/python3.9/dist-packages/blindai/client.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, addr, unattested_server_port, attested_server_port, model_management_port, hazmat_manifest_path, hazmat_http_on_unattested_port, simulation_mode, use_cloud_manifest)\u001b[0m\n\u001b[1;32m    604\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 605\u001b[0;31m                 validate_attestation(\n\u001b[0m\u001b[1;32m    606\u001b[0m                     \u001b[0mquote\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.9/dist-packages/blindai/_dcap_attestation.py\u001b[0m in \u001b[0;36mvalidate_attestation\u001b[0;34m(quote, collateral, enclave_held_data, manifest_path, use_cloud_manifest)\u001b[0m\n\u001b[1;32m    187\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mmanifest_path\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0muse_cloud_manifest\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 188\u001b[0;31m         raise TypeError(\n\u001b[0m\u001b[1;32m    189\u001b[0m             \u001b[0;34m\"Input inconsistency. You cannot set a manifest path and ask to use the cloud manifest in the same time\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: Input inconsistency. You cannot set a manifest path and ask to use the cloud manifest in the same time",
      "\nDuring handling of the above exception, another exception occurred:\n",
      "\u001b[0;31mAttestationError\u001b[0m                          Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-6-9ac48413e7b9>\u001b[0m in \u001b[0;36m<cell line: 3>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0mget_ipython\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msystem\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'touch fake_manifest.toml'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m connection = blindai.core.connect(\n\u001b[0m\u001b[1;32m      4\u001b[0m             \u001b[0mDEFAULT_BLINDAI_ADDR\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m             \u001b[0mhazmat_http_on_unattested_port\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.9/dist-packages/blindai/client.py\u001b[0m in \u001b[0;36mconnect\u001b[0;34m(addr, unattested_server_port, attested_server_port, model_management_port, hazmat_manifest_path, hazmat_http_on_unattested_port, simulation_mode, use_cloud_manifest)\u001b[0m\n\u001b[1;32m    838\u001b[0m     \"\"\"\n\u001b[1;32m    839\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 840\u001b[0;31m     return BlindAiConnection(\n\u001b[0m\u001b[1;32m    841\u001b[0m         \u001b[0maddr\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    842\u001b[0m         \u001b[0munattested_server_port\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.9/dist-packages/blindai/client.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, addr, unattested_server_port, attested_server_port, model_management_port, hazmat_manifest_path, hazmat_http_on_unattested_port, simulation_mode, use_cloud_manifest)\u001b[0m\n\u001b[1;32m    613\u001b[0m                 \u001b[0;32mraise\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    614\u001b[0m             \u001b[0;32mexcept\u001b[0m \u001b[0mException\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 615\u001b[0;31m                 \u001b[0;32mraise\u001b[0m \u001b[0mAttestationError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Attestation verification failed\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    616\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    617\u001b[0m         \u001b[0;31m# requests (http library) takes a path to a file containing the CA\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mAttestationError\u001b[0m: Attestation verification failed"
     ]
    }
   ],
   "source": [
    "# !touch fake_manifest.toml\n",
    "\n",
    "# connection = blindai.core.connect(\n",
    "#             DEFAULT_BLINDAI_ADDR,\n",
    "#             hazmat_http_on_unattested_port=True,\n",
    "#             use_cloud_manifest=True,\n",
    "#             hazmat_manifest_path=\"./fake_manifest.toml\"\n",
    "#         )"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "id": "cJPrmN-1UPvY"
   },
   "source": [
    "This causes the connection to be refused with an `AttestationError` because the application code cannot be verified.\n",
    "\n",
    "> **Note**\n",
    ">\n",
    "> To test this more thoroughly, you can download our GitHub project and modify the server code stored in the `src` folder very slightly. \n",
    ">\n",
    ">You then need to generate a new `manifest.toml` based on this modified source code by building the project. Once this is done, replace the path to the `fake_manifest.toml` in the previous example with a path to your newly generated `manifest.toml`. This will lead to the same error, since the server's hash received in the attestation report will not match the code in the newly generated `manifest.toml`."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "id": "jgy_QBukXViJ"
   },
   "source": [
    "### Querying the model\n",
    "\n",
    "Once connected, the `transcribe()` method will prepare the audio file correctly for the model and call the BlindAI.Core `run_model()` method, passing it the ID for the default Whisper model and the now pre-processed input data:\n",
    "\n",
    "```py\n",
    "res = connection.run_model(model_hash=DEFAULT_WHISPER_MODEL, input_tensors=input_data)\n",
    "```\n",
    "\n",
    "Then, the method extracts the text transcription from the returned object and returns that to our BlindAI API user!\n",
    "\n",
    "\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "id": "9dLZ16T528YV"
   },
   "source": [
    "## Conclusions\n",
    "____________________________\n",
    "\n",
    "We have seen:\n",
    "- How to **confidentially transcribe audio** using the Whisper model in BlindAI API.\n",
    "- How **privacy** is guaranteed **under the hood**.\n",
    "\n",
    "Please check out the rest of our BlindAI documentation to see more examples of how you can use BlindAI to query AI models without compromising the safety of user data or models."
   ]
  }
 ],
 "metadata": {
    "mkdocs": {
        "description": "Transcribe audio privately with Whisper and BlindAI API: Install Python library, transcribe securely with hardware attestation."
    },
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": "blindai-preview-7Yaoi9am-py3.8",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
